/**axios封装
 * 请求拦截、相应拦截、错误统一处理
 */
import { CreateAxiosDefaults, AxiosResponse } from 'axios'
import axios from 'axios'
import { tokenName, excludesRequestPath, type RequestCode } from './base.js'
import { Notify } from 'vant'

// import { ElMessage as Message } from 'element-plus';
const Message = function ({ message, type }: any) {
  Notify({ type: 'danger', message })
}

const getToken = function (): string {
  const tokenStr: string | null = localStorage.getItem(tokenName)
  let token = ''
  try {
    const userInfo: { token: string; username: string } = JSON.parse(tokenStr || '')
    token = userInfo.token || userInfo.username
  } catch (e) {}
  return token
}
// 环境跟目录
const baseURL: string = ''

const _config: CreateAxiosDefaults = {
  baseURL: baseURL, // url = base url + request url
  withCredentials: true, // send cookies when cross-domain requests
  timeout: 30000, // request timeout
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
}

const service = axios.create(_config)
const successCode = 200

// 请求拦截器
service.interceptors.request.use(
  (config: any) => {
    if (!excludesRequestPath.includes(config.url)) {
      //添加token
      const token = getToken()
      if (!token) {
        /**
         * 通过vue-router 进行前置导航守卫进行token验证和登录，因此这里只需要刷新页面，其他的交给导航首位处理
         */
        location.reload()

        return
      }
      //添加header
      token && ((config.headers.Authorization = token), (config.headers['X-Token'] = token))
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器

service.interceptors.response.use(
  (response: AxiosResponse) => {
    if (response.status === 200) {
      // 抛出异常
      if (response.data.code != successCode) {
        return Promise.reject(errorCode(response.data.code, response))
      }
      return Promise.resolve(response)
    } else {
      Message({
        message:
          response.data.message ||
          response.data.msg ||
          response.data.errMsg ||
          '网络响应未知错误错误！',
        type: 'error'
      })
      return Promise.reject(response)
    }
  },
  // 服务器状态码不是200的情况
  error => {
    if (error.response.status) {
      errorCode(error.response.status, error.response)
      return Promise.reject(error.response)
    }
  }
)
/**
 * 状态码
 * @param {number,string}} code
 * @param {*} response
 * @returns
 */
const errorCode = function (code: number | string, response: AxiosResponse): AxiosResponse {
  // Message.closeAll();
  switch (+code) {
    /**
     * 401:  未登录
     * 未登录则跳转登录页面，并携带当前页面的路径
     * 在登录成功后返回当前页面，这一步需要在登录页操作。
     */
    case 401:
      Message({
        message: response.data.msg || response.data.message || '网络请求失败，未知错误！',
        type: 'error'
      })
      localStorage.setItem(tokenName, '')
      //通过vue-router 进行前置导航守卫进行token验证和登录，因此这里只需要刷新页面，其他的交给导航首位处理
      window.location.reload()

      break
    /**
     *  403 token过期
     *  清除本地token和清空vuex中token对象
     *  跳转登录页面
     */
    case 403:
      Message({ message: '登录过期，请重新登录', type: 'error' })
      // 清除token
      localStorage.setItem(tokenName, '')
      //通过vue-router 进行前置导航守卫进行token验证和登录，因此这里只需要刷新页面，其他的交给导航首位处理
      window.location.reload()

      break
    /**
     *  429请求不存在
     */
    case 429:
      console.log('接口请求过于频繁，请检查相同接口是否多方调用或多次调用')
      break
    /**
     *  404请求不存在
     */
    case 404:
      Message({ message: '404网络请求不存在', type: 'error' })
      break
    /**
     * 其他错误
     */
    default:
      Message({
        message: response.data.message || response.data.msg || '网络请求失败，未知错误！',
        type: 'error'
      })
  }
  return response
}

/**
 * 统一接管不同请求返回的结果处理
 */
/**
 * 统一接管不同请求返回的结果处理
 */
const promiseMethods = function (
  method: Promise<RequestCode>,
  resolve: (value: RequestCode) => void,
  reject: (value: any) => void
) {
  method
    .then(res => {
      if (res.data.code != successCode) {
        reject(res.data)
        return
      }
      resolve(res.data)
    })
    .catch(err => {
      reject({
        msg: `出现错误:【${err?.status}】${err?.statusText}`,
        ...(err || { data: { code: '', data: '' } }).data
      })
    })
}

/**
 * get方法，对应get请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function get(url: string, params?: any): Promise<RequestCode> {
  return new Promise((resolve, reject) => {
    promiseMethods(
      service.get(url, {
        params: params
      }),
      resolve,
      reject
    )
  })
}

/**
 * post方法，对应post请求
 * @param {String} url [请求的url地址]
 * @param {Object} params [请求时携带的参数]
 */
export function post(url: string, params?: any): Promise<RequestCode> {
  return new Promise((resolve, reject) => {
    promiseMethods(service.post(url, params), resolve, reject)
  })
}
/**
 * 删除
 * @param {Object} url
 * @param {Object} params
 */
function _delete(url: string, params?: any): Promise<RequestCode> {
  return new Promise((resolve, reject) => {
    promiseMethods(service.delete(url, { params, data: params }), resolve, reject)
  })
}
export const deletes = _delete
export const remove = _delete

/**
 * put
 * @param {Object} url
 * @param {Object} params
 */
export function put(url: string, params?: any): Promise<RequestCode> {
  return new Promise((resolve, reject) => {
    promiseMethods(service.put(url, params), resolve, reject)
  })
}

export { service as request, type RequestCode }
